package mage.factory.handler;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Hashtable;
import java.util.List;

import org.xml.sax.Attributes;
import org.xml.sax.SAXException;

public class CardHandler extends DefaultHandler{
	protected String CARD = "card";
	protected String NAME = "name";
	
	protected String COST = "cost";
	protected String LOYALITY = "loyalty";
	//protected String TYPELIST = "typelist";
	protected String TYPE = "type";
	protected String POW = "pow";
	protected String TGH = "tgh";
	protected String HAND = "hand";
	protected String LIFE = "life";
	//protected String RULELIST = "rulelist";
	protected String RULE = "rule";
	protected String MULTI = "multi";
    
	protected boolean isMulti = false;
	protected boolean isCardValid(){
		return true;
	}
	protected CardElement current_element = null;
	protected Hashtable<String,ArrayList<MetaElement>> name_to_set = null;
	
	
	public void setNameToSet(Hashtable<String,ArrayList<MetaElement>> name_to_set){
		this.name_to_set=name_to_set;
	}
	public String codeToName(String code,List<DefaultHandlerElement> elements){
		Hashtable<String,String> res = new Hashtable<String, String>();
		for (int i=0; i < elements.size();i++){
			SetElement se = (SetElement)elements.get(i);
			res.put(se.getCode(),se.getPackageName());
		}
		String packagename = res.get(code);
		if (packagename == null || packagename.length()<1){
			packagename = code;
		}
		return packagename;
	}
	@Override
	public void startElement(String qName, Attributes attributes)throws SAXException {
		if(this.CARD.equalsIgnoreCase(qName)){this.current_element=new CardElement();}
		if(this.MULTI.equalsIgnoreCase(qName)){
			this.isMulti=true;
			this.current_element.setMultiType(attributes.getValue("type"));
		}
	}
	@Override
	public void endElement(String qName,String characters) throws SAXException {
		if(this.NAME.equalsIgnoreCase(super.getCurrentElement())){
			if(this.current_element.getName().equalsIgnoreCase("")){
				this.current_element.setName(characters);
			}
			if(this.isMulti){
				this.current_element.setName(characters);
			}
			
		}
		if(this.RULE.equalsIgnoreCase(super.getCurrentElement()) && this.isCardValid()){this.current_element.addRule(characters.trim());}
		
		if(this.CARD.equalsIgnoreCase(qName) ){
			if(this.isCardValid()){
				this.elements.add(this.current_element);
			}
		}
		if(this.MULTI.equalsIgnoreCase(qName)){
			this.isMulti=false;
		}
	}
	@Override
	public boolean characters(String characters) throws SAXException {
		if(this.NAME.equalsIgnoreCase(super.getCurrentElement())){
			if(!super.isElementAlreadyExisting(characters,"")){
				if(this.name_to_set.get(characters)!=null){
					this.current_element.setName(characters);
					this.current_element.setSet(this.name_to_set.get(characters));
				}
			}else{
				this.current_element=null;
				super.current_element_valid=false;
			}
			return true;
		}
		if(this.MULTI.equalsIgnoreCase(super.getCurrentElement()) && this.isCardValid()){this.current_element.setMulti(this.isMulti);return true;}
		if(this.COST.equalsIgnoreCase(super.getCurrentElement()) && this.isCardValid()){this.current_element.setCost(characters.trim());return true;}
		if(this.LOYALITY.equalsIgnoreCase(super.getCurrentElement()) && this.isCardValid()){this.current_element.setLoyalty(characters.trim());return true;}
		if(this.TYPE.equalsIgnoreCase(super.getCurrentElement()) && this.isCardValid()){this.current_element.addType(characters.trim());return true;}
		if(this.POW.equalsIgnoreCase(super.getCurrentElement()) && this.isCardValid()){this.current_element.setPow(characters.trim());return true;}
		if(this.TGH.equalsIgnoreCase(super.getCurrentElement()) && this.isCardValid()){this.current_element.setTgh(characters.trim());return true;}
		if(this.HAND.equalsIgnoreCase(super.getCurrentElement()) && this.isCardValid()){this.current_element.setHand(characters.trim());return true;}
		if(this.LIFE.equalsIgnoreCase(super.getCurrentElement()) && this.isCardValid()){this.current_element.setLife(characters.trim());return true;}
		return false;		
	}
	
	@Override
	public void toFile(String basepath){
		try {
			BufferedWriter out = new BufferedWriter(new FileWriter(
						new File(
								"completelist.csv"
								)
					));
			out.write("NAME;SET;RARITY;NUMBER;COST;POW;TGH;LOYALTY;LIFE;HAND;LEGENDARY;TYPE1;TYPE2;SUBTYPE1;SUBTYPE2;OTHER1;OTHER2;OTHER3;OTHER4;MULTI;M_NAME;M_COST;M_POW;M_TGH;M_LEGEND;M_TYPE1;M_TYPE2;M_SUBTYPE1;M_SUBTYPE2;M_OTHER1;M_OTHER2;M_OTHER3;M_OTHER4;M_RULE;RULE\n");
			for (DefaultHandlerElement se : this.elements) {
				out.write(se.toClass());
			}
			out.close();
		} catch (IOException e) {
		}
	}
}
class CardElement implements DefaultHandlerElement{
	protected String name = "";
	protected List<MetaElement> set = new ArrayList<MetaElement>();
	protected String packagename = null;
	
	protected String cost = "";
	protected String loyalty = "";
	//protected String typelist = "";
	protected List<String> type = new ArrayList<String>();
	protected String pow = "";
	protected String tgh = "";
	protected String hand = "";
	protected String life = "";
	protected List<String> rule = new ArrayList<String>();
	protected String multi_type = "";
	protected CardElement multi = null;
	
	protected boolean isMulti = false;
	protected String legendary = "";
	@Override
	public String toClass() {
		StringBuffer sb = new StringBuffer();
		for (int i=0; i < this.getSets().length; i++){
			sb.append(this.getName().trim()+";");
			sb.append(this.getSets()[i].trim()+";");
			sb.append(this.getRaritys()[i].trim()+";");
			sb.append(this.getNumbers()[i].trim()+";");
			sb.append(this.getCost().trim()+";");
			sb.append(this.getPow().trim()+";");
			sb.append(this.getTgh().trim()+";");
			sb.append(this.getLoyalty().trim()+";");
			sb.append(this.getHand().trim()+";");
			sb.append(this.getLife().trim()+";");
			sb.append(this.getLegendary().trim()+";");
			sb.append(this.getMainType().trim());
			sb.append(this.getSubType().trim());
			sb.append(this.getOtherType().trim());
			sb.append(this.multi_type+";");
			if(this.multi!=null){
				sb.append(this.multi.getName()+";");
				sb.append(this.multi.getCost().trim()+";");
				sb.append(this.multi.getPow().trim()+";");
				sb.append(this.multi.getTgh().trim()+";");
				sb.append(this.multi.getLegendary().trim()+";");
				sb.append(this.multi.getMainType().trim());
				sb.append(this.multi.getSubType().trim());
				sb.append(this.multi.getOtherType().trim());
				sb.append(this.multi.getRule()+";");
			}else{
				sb.append(";");
				sb.append(";");
				sb.append(";");
				sb.append(";");
				sb.append(";");
				sb.append(";;");
				sb.append(";;");
				sb.append(";;;;");
				sb.append(";");
			}
			sb.append(this.getRule().trim()+";");
			sb.append("\n");
		}
		
		
		return sb.toString();
	}
	public boolean isMulti(){
		return this.multi!=null;
	}
	public CardElement getMulti(){
		return this.multi;
	}
	public void setMulti(boolean multi){
		this.isMulti=multi;
		if(this.isMulti){
			this.multi=new CardElement();
		}
	}
	public void setMultiType(String multi_type){
		this.multi_type=multi_type;
	}
	@Override
	public String getPackageName() {
		return this.packagename;
	}
	public void setPackageName(String packagename){
		this.packagename=packagename;
	}
	public void addType(String type){
		if(this.isMulti){
			if("Legendary".equalsIgnoreCase(type)){
				this.multi.legendary=type;
			}else{
				this.multi.type.add(type);
			}
		}else{
			if("Legendary".equalsIgnoreCase(type)){
				this.legendary=type;
			}else{
				this.type.add(type);
			}
		}
	}
	public String getLegendary(){
		return this.legendary;
	}
	public List<String> getTypeList(){
		return this.type;
	}
	public String getType(){
		StringBuffer sb = new StringBuffer();
		for (String s : this.type) {
			sb.append(s.trim()+"|");
		}
		if(sb.length()>1){
			sb.deleteCharAt(sb.length()-1);
		}
		return sb.toString();
	}
	public String getMainType(){
		StringBuffer sb = new StringBuffer();
		int t=0;
		if(this.type.contains("Artifact")){t++;sb.append("Artifact;");}
		if(this.type.contains("Enchantment")){t++;sb.append("Enchantment;");}
		if(this.type.contains("Instant")){t++;sb.append("Instant;");}
		if(this.type.contains("Land")){t++;sb.append("Land;");}
		if(this.type.contains("Planeswalker")){t++;sb.append("Planeswalker;");}
		if(this.type.contains("Sorcery")){t++;sb.append("Sorcery;");}
		if(this.type.contains("Tribal")){t++;sb.append("Tribal;");}
		if(this.type.contains("Creature")){t++;sb.append("Creature;");}

		if(this.type.contains("Basic")){t++;sb.append("Basic;");}
		
		//FIXME: Not implemented Yet
		if(this.type.contains("Plane")){t++;sb.append("Plane;");}
		if(this.type.contains("Scheme")){t++;sb.append("Scheme;");}
		if(this.type.contains("Vanguard")){t++;sb.append("Vanguard;");}
		
		while(t<2){
			t++;
			sb.append(";");
		}
		return sb.toString();
	}
	public String getSubType(){
		StringBuffer sb = new StringBuffer();
		int t=0;
		if(this.type.contains("Aura")){t++;sb.append("Aura;");}
		if(this.type.contains("Equipment")){t++;sb.append("Equipment;");}
		if(this.type.contains("Fortification")){t++;sb.append("Fortification;");}
		if(this.type.contains("Snow")){t++;sb.append("Snow;");}
		if(this.type.contains("Shrine")){t++;sb.append("Shrine;");}
		if(this.type.contains("World")){t++;sb.append("World;");}
		if(this.type.contains("Arcane")){t++;sb.append("Arcane;");}
		if(this.type.contains("Trap")){t++;sb.append("Trap;");}
		if(this.type.contains("Lair")){t++;sb.append("Lair;");}
		if(this.type.contains("Locus")){t++;sb.append("Locus;");}
		if(this.type.contains("Urza’s")){t++;sb.append("Urza’s;");}
		if(this.type.contains("Ongoing")){t++;sb.append("Ongoing;");}
		
		
		while(t<2){
			t++;
			sb.append(";");
		}
		return sb.toString();
	}
	public String getOtherType(){
		ArrayList<String> temp = new ArrayList<String>(this.type);
		String[] main = this.getMainType().split(";");
		String[] sub = this.getSubType().split(";");
		for (int i=0; i <main.length; i++){
			temp.remove(main[i]);
		}
		for (int i=0; i <sub.length; i++){
			temp.remove(sub[i]);
		}
		StringBuffer sb = new StringBuffer();
		int t=0;
		for (String string : temp) {
			t++;
			sb.append(string+";");
		}
		while(t<4){
			t++;
			sb.append(";");
		}
		return sb.toString();
	}
	
	public String getSet(){
		StringBuffer sb = new StringBuffer();
		ArrayList<String> temp_set = new ArrayList<String>();
		if(this.set!=null){
			for (MetaElement s : this.set) {
				if(!temp_set.contains(s)){
					temp_set.add(s.getSet());
				}
			}
			for (String s : temp_set) {
				sb.append(s.trim()+"|");
			}
			if(sb.length()>1){
				sb.deleteCharAt(sb.length()-1);
			}
		}
		return sb.toString();
	}
	public String[] getSets(){
		return this.getSet().split("\\|");
	}
	public String getRarity(){
		StringBuffer sb = new StringBuffer();
		ArrayList<String> temp_set = new ArrayList<String>();
		if(this.set!=null){
			for (MetaElement s : this.set) {
				if(!temp_set.contains(s)){
					temp_set.add(s.getRarity());
				}
			}
			for (String s : temp_set) {
				sb.append(s.trim()+"|");
			}
			if(sb.length()>1){
				sb.deleteCharAt(sb.length()-1);
			}
		}
		return sb.toString();
	}
	public String[] getRaritys(){
		return this.getRarity().split("\\|");
	}
	public String getNumber(){
		StringBuffer sb = new StringBuffer();
		ArrayList<String> temp_set = new ArrayList<String>();
		if(this.set!=null){
			for (MetaElement s : this.set) {
				if(!temp_set.contains(s)){
					temp_set.add(s.getNumber());
				}
			}
			for (String s : temp_set) {
				sb.append(s.trim()+"|");
			}
			if(sb.length()>1){
				sb.deleteCharAt(sb.length()-1);
			}
		}
		return sb.toString();
	}
	public String[] getNumbers(){
		return this.getNumber().split("\\|");
	}
	public void setSet(ArrayList<MetaElement> set){
		if(this.isMulti){
			this.multi.setSet(set);
		}else{
			this.set=set;
		}
	}
	public void addRule(String rule){
		if(this.isMulti){
			this.multi.rule.add(rule);
		}else{
			this.rule.add(rule);
		}
	}
	public String getRule(){
		StringBuffer sb = new StringBuffer();
		if(this.rule!=null){
			for (String s : this.rule) {
				String temp = s.trim();
				if (temp.length()>0){
					sb.append(s.trim()+"|");
				}
			}
			if(sb.length()>1){
				if ("|".equalsIgnoreCase(""+sb.charAt(sb.length()-1))){
					sb.deleteCharAt(sb.length()-1);
				}
			}
		}
		return sb.toString();
	}
	@Override
	public String getClassName() {
		return this.getName().replace(" ","").replaceAll("'","").replaceAll("\"","");
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		if(this.isMulti){
			this.multi.setName(name);
		}else{
			this.name = name;
		}
	}
	public String getCost() {
		return cost;
	}
	public void setCost(String cost) {
		if(this.isMulti){
			this.multi.setCost(cost);
		}else{
			this.cost = cost;
		}
	}
	public String getLoyalty() {
		return loyalty;
	}
	public void setLoyalty(String loyalty) {
		if(this.isMulti){
			this.multi.setLoyalty(loyalty);
		}else{
			this.loyalty = loyalty;
		}
	}
	public String getPow() {
		return pow;
	}
	public void setPow(String pow) {
		if(this.isMulti){
			this.multi.setPow(pow);
		}else{
			this.pow = pow;
		}
	}
	public String getTgh() {
		return tgh;
	}
	public void setTgh(String tgh) {
		if(this.isMulti){
			this.multi.setTgh(tgh);
		}else{
			this.tgh = tgh;
		}
	}
	public String getHand() {
		return hand;
	}
	public void setHand(String hand) {
		if(this.isMulti){
			this.multi.setHand(hand);
		}else{
			this.hand = hand;
		}
	}
	public String getLife() {
		return life;
	}
	public void setLife(String life) {
		if(this.isMulti){
			this.multi.setLife(life);
		}else{
			this.life = life;
		}
	}
	
}